﻿using TrueSync;
using UnityEngine;

namespace HEFramework
{
    public static class SkillCooldownComponentSystem
    {
        [EntitySystem]
        public class SkillCooldownComponentAwakeSystem : AwakeSystem<SkillCooldownComponent>
        {
            protected override void Awake(SkillCooldownComponent _self)
            {
            }
        }


        [EntitySystem]
        public class SkillCooldownComponentUpdateSystem : UpdateSystem<SkillCooldownComponent>
        {
            protected override void Update(SkillCooldownComponent _self)
            {
                _self.UpdateSkillCooldown();
            }
        }


        public static int Ready(this SkillCooldownComponent _self, int _id, bool _isActive)
        {
            SkillCooldownData data;
            _self.Datas.TryGetValue(_id, out data);
            if (data == null)
            {
                return (int)eSkillErrorCode.System;
            }

            if (_isActive)
            {
                if (data.ACooldown > 0)
                {
                    return (int)eSkillErrorCode.Lack_CD;
                }
            }
            else
            {
                if (data.PCooldown > 0)
                {
                    return (int)eSkillErrorCode.Lack_CD;
                }
            }

            return (int)eSkillErrorCode.None;
        }

        public static void SetSkillCooldown(this SkillCooldownComponent _self, int _id, bool _isActive)
        {
            SkillCooldownData data;
            _self.Datas.TryGetValue(_id, out data);
            if (data == null)
            {
                return;
            }

            FP cd = _self.Skill_CD(_id, _isActive);
            if (_isActive)
            {
                data.ACooldown = cd;
            }
            else
            {
                data.PCooldown = cd;
            }
        }

        public static void AddSkillCooldownData(this SkillCooldownComponent _self, int _id)
        {
            if (_self.Datas.ContainsKey(_id))
            {
                return;
            }

            var data = _self.GetNewSkillCooldownData(_id);
            if (data == null)
            {
                return;
            }

            _self.Datas.Add(_id, data);
        }

        public static void RemoveSkillCooldownData(this SkillCooldownComponent _self, int _id)
        {
            if (!_self.Datas.ContainsKey(_id))
            {
                return;
            }

            _self.Datas.Remove(_id);
        }


        public static FP Sill_CD_PCT(this SkillCooldownComponent _self, int _id, bool _isActive)
        {
            SkillCooldownData data;
            _self.Datas.TryGetValue(_id, out data);
            if (data == null)
            {
                return 0;
            }

            FP cd = _self.Skill_CD(_id, _isActive);

            if (cd == 0)
            {
                return cd;
            }

            if (_isActive)
            {
                return TSMath.Min(data.ACooldown / cd, 1);
            }
            else
            {
                return TSMath.Min(data.PCooldown / cd, 1);
            }
        }

        public static FP Skill_CD(this SkillCooldownComponent _self, int _id, bool _isActive)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var ac = _self.GetMainEntity().GetChild<AttributeComponent>();

            if (dc == null || ac == null)
            {
                return 0;
            }

            var sData = dc.LoadDataTable<DRSkill>().GetData(_id);
            if (_isActive)
            {
                return Formula.CD(Formula.TM(sData.ACooldown), ac.M_ATK_SP);
            }
            else
            {
                return Formula.CD(Formula.TM(sData.PCooldown), ac.M_ATK_SP);
            }
        }

        private static SkillCooldownData GetNewSkillCooldownData(this SkillCooldownComponent _self, int _id)
        {
            SkillCooldownData data = new SkillCooldownData();
            data.ID = _id;
            data.PCooldown = 0;
            data.ACooldown = 0;
            return data;
        }


        private static void UpdateSkillCooldown(this SkillCooldownComponent _self)
        {
            FP deltaTime = Time.deltaTime;
            foreach (var data in _self.Datas.Values)
            {
                data.PCooldown -= deltaTime;
                if (data.PCooldown <= 0)
                {
                    data.PCooldown = 0;
                }

                data.ACooldown -= deltaTime;
                if (data.ACooldown <= 0)
                {
                    data.ACooldown = 0;
                }
            }
        }


        private static Entity GetMainEntity(this SkillCooldownComponent _self)
        {
            return _self.Parent.Parent;
        }
    }
}